/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.ufrn.engcomp.mpc.domain;

/**
 *
 * @author Felipe
 */
public abstract class AbstractPredictiveController implements PredictiveController {
    protected Plant plant;
    
    // Monitor para as alterações nos parâmetros serem thread-safe
    protected final Object parameterChangeMonitor = new Object();
    
    // Parâmetros de sintonia do controlador
    protected int hw;
    protected int hp;
    protected int hu;
    protected double[] q;
    protected double[] r;
    protected int nStateVariables;
    protected int nInputs;
    protected int nOutputs;
    
    public AbstractPredictiveController(Plant plant) {
        this.plant = plant;
        
        nStateVariables = plant.getAMatrix().getRowDimension();
        nInputs = plant.getBMatrix().getColumnDimension();
        nOutputs = plant.getCMatrix().getRowDimension();
        
        init();
    }
    
    private void init() {
        initEnviroment();
    }
    
    protected abstract double[] synchComputeU(double[] setPoint, double[] lastX, double[] lastY, double[] lastU, double[] lastStep);
    
    protected abstract double[] synchComputeU(double[] setPoint, double[] lastX, double[] lastY, double[] lastU, double[] lastStep, double d);
    
    protected abstract void initEnviroment();
    
    protected abstract void initStaticData();
    
    @Override
    public final double[] computeU(double[] setPoint, double[] lastX, double[] lastY, double[] lastU, double[] lastStep) {
        synchronized (parameterChangeMonitor) {
            return synchComputeU(setPoint, lastX, lastY, lastU, lastStep);
        }
    }
    
    @Override
    public final double[] computeU(double[] setPoint, double[] lastX, double[] lastY, double[] lastU, double[] lastStep, double d) {
        synchronized (parameterChangeMonitor) {
            return synchComputeU(setPoint, lastX, lastY, lastU, lastStep, d);
        }
    }

    @Override
    public final Object[] getParameters() {
        return new Object[] { hw, hp, hu, q, r };
    }

    @Override
    public final void setParameters(int hw, int hp, int hu, double[] q, double[] r) {
        synchronized (parameterChangeMonitor) {
            this.hw = hw;
            this.hp = hp;
            this.hu = hu;
            this.q = q;
            this.r = r;
            
            initStaticData();
        }
    }

}
